package com.yuanli.card.authentication.core.realm;

import com.yuanli.card.authentication.core.PasswordUtil;
import com.yuanli.card.authentication.service.ISysResourcesService;
import com.yuanli.card.authentication.service.ISysRoleService;
import com.yuanli.card.authentication.service.ISysUserService;
import com.yuanli.card.enumeration.UserStatusEnum;
import com.yuanli.card.pojo.SysResources;
import com.yuanli.card.pojo.SysRole;
import com.yuanli.card.pojo.SysUser;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;

import static org.apache.log4j.helpers.LogLog.error;

/**
 * Created by layne on 2018/5/24.
 */
public class ShiroRealm extends AuthorizingRealm {
    @Resource
    private ISysUserService userService;
    @Resource
    private ISysResourcesService iSysResourcesService;
    @Resource
    private ISysRoleService iSysRoleService;

    /**
     * 提供账户信息返回认证信息（用户的角色信息集合）
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //获取用户的输入的账号.
        String username = (String) token.getPrincipal();
        SysUser sysUser = userService.findByUserName(username);
        if (sysUser == null) {
            throw new UnknownAccountException("账号不存在！");
        }
        if (sysUser.getStatus() != null && UserStatusEnum.DISABLE.getCode().equals(sysUser.getStatus())) {
            throw new LockedAccountException("帐号已被锁定，禁止登录！");
        }


        try {
            String decrypt = PasswordUtil.decrypt(sysUser.getPassword(), sysUser.getSalt());
            // principal参数使用用户Id，方便动态刷新用户权限
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                    sysUser.getUsername(),
                    decrypt,
                    ByteSource.Util.bytes(sysUser.getSalt()),
                    getName());
            SecurityUtils.getSubject().getSession().setAttribute("userSession", sysUser);
            return authenticationInfo;
        } catch (Exception e) {
            error("AES 解密出错", e);
            SecurityUtils.getSubject().getSession().removeAttribute("userSession");
            return null;
        }
    }

    /**
     * 权限认证，为当前登录的Subject授予角色和权限（角色的权限信息集合）
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 权限信息对象info,用来存放查出的用户的所有的角色（role）及权限（permission）
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        Long userId = (Long) SecurityUtils.getSubject().getPrincipal();

        // 赋予角色
        List<SysRole> sysRoleList = iSysRoleService.findRolesByUserId(userId);
        for (SysRole sysRole : sysRoleList) {
            info.addRole(sysRole.getName());
        }

        // 赋予权限
        List<SysResources> sysResourcesList = iSysResourcesService.listByUserId(userId);
        if (!CollectionUtils.isEmpty(sysResourcesList)) {
            for (SysResources sysResources : sysResourcesList) {
                String permission = sysResources.getPermission();
                if (!StringUtils.isEmpty(permission)) {
                    info.addStringPermission(permission);
                }
            }
        }
        return info;
    }
}
